package com.markhsiu.result;

import java.io.IOException;
import java.util.*;

/**
 *
 * @author mou.sunm
 * @date 2018/07/02
 */
public class ABadFit extends DataAbsract{

    private List<String> result = new ArrayList<>(70000);
    // 参数
    public static final double alpha = 10.;
    //50%
    public static final double beta = 0.5;


    public double evaluate() throws IOException {
        double costs = 0.;
        int num = 0;
        Set<Integer> machineSet = new HashSet<>();
        try {

            /** 逐行执行 */
            for(Map.Entry<Integer, Integer> entry : inst2AppIndex.entrySet()){
                Integer inst = entry.getKey();
                int appIt = inst2AppIndex.get(inst);

                for(int i = 0; i< m;i++){
                    Integer machineIt = i;

                    if (toMachine(appIt, inst, machineIt)){
                        String r = "inst_"+(inst+1)+","+"machine_"+(i+1);
                        num++;
                        if(num % 1000 == 0){
                            System.out.println(num+" "+r);
                        }
                        result.add(r);
                        machineSet.add(machineIt);
                        break;
                    }
                }

            }



            System.out.println("machine size = "+machineSet.size());
            /** 计算终态得分 */
            // 检查inst是否全部放入machine
            for (int inst : inst2AppIndex.keySet()) {
                if (!inst2Machine.containsKey(inst)) {
                    throw new Exception("instance未全部分配"+inst);
                }
            }
            // 检查machine的终态
            for (int j = 0; j < m; j++) {
                Map<Integer, Integer> hasApp = machineHasApp[j];
                if (hasApp.size() == 0) {
                    continue;
                }
                // 检查互斥条件
                for (Integer conditionalApp : hasApp.keySet()) {
                    if (hasApp.get(conditionalApp) <= 0) {
                        throw new Exception("[DEBUG 1]Stupid Judger.");
                    }
                    for (Integer checkApp : appInterference[conditionalApp].keySet()) {
                        if (hasApp.containsKey(checkApp)) {
                            if (hasApp.get(checkApp) > appInterference[conditionalApp].get(checkApp)) {
                                throw new Exception("终态存在干扰冲突");
                            }
                        }
                    }
                }
                // 检查资源限制
                for (int i = 0; i < k; i++) {
                    if (dcmp(machineResourcesUsed[j][i] - machineResources[j][i]) > 0) {
                        throw new Exception("终态存在资源过载");
                    }
                }
                // 技术得分
                for (Integer t : cpuIter) {
                    double usage = machineResourcesUsed[j][t] / machineResources[j][t];
                    costs += 1. + alpha * (Math.exp(Math.max(0., usage - beta)) - 1.);
                }
            }
            costs /= T;
        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
            costs = 1e9;
        }
        return costs;
    }


    @Override
    protected boolean toMachine(int appIt, int inst, int machineIt) {
        return toMachine(appIt, inst, machineIt, true);
    }

    @Override
    protected boolean toMachine(int appIt, int inst, int machineIt, boolean doCheck) {
        if(appIt < 0){
            appIt = inst2AppIndex.get(inst);
        }


        Map<Integer, Integer> hasApp = machineHasApp[machineIt];

        Integer cnt = hasApp.get(appIt);

        if (doCheck) {
            // 检查互斥规则
            int nowHas = 0;
            if (cnt != null) {
                nowHas = cnt;
            }
            for (Map.Entry<Integer,Integer> entry : hasApp.entrySet()) {
                Integer appItLimit = appInterference[appIt].get(entry.getKey());
                if (appItLimit != null) {
                    if (entry.getValue() > appItLimit) {
                        return false;
                    }
                }

                if (entry.getValue() <= 0) {
                    continue;
                }

                Integer appLimit = appInterference[entry.getKey()].get(appIt);
                if (appLimit != null) {
                    if (nowHas + 1 > appLimit) {
                        return false;
                    }
                }
            }

            // 检查资源限制
            for (int i = 0; i < k; i++) {
                if ((machineResourcesUsed[machineIt][i] + appResources[appIt][i] - machineResources[machineIt][i]) > 0) {
                    return false;
                }
            }
        }
        // 将inst放入新的machine
        inst2Machine.put(inst, machineIt);

        if(cnt == null){
            cnt = 0;
        }
        hasApp.put(appIt, cnt + 1);
        for (int i = 0; i < k; i++) {
            machineResourcesUsed[machineIt][i] += appResources[appIt][i];
        }

        return true;
    }





    private int dcmp(double x) {
        if (Math.abs(x) < 1e-9) {
            return 0;
        }
        return x < 0. ? -1 : 1;
    }


    public List<String> getResult(){
        return result;
    }

}
